<template>
    <div class="app-container">
      <U02Anim/>
      <el-container>
          <el-aside width="68%"
                    style="background-color: #8f72ba22;"
          >
              <h3>
                Hi，{{ U1.name }}！{{[4,5,6,7,8].includes(ed.now.getMonth()) ? '🍹' : '☀️'}}
                欢迎来到<span style="color: var(--el-color-primary);">H3C AI</span>测试脚本生成系统
              </h3>
          </el-aside>
          <el-main>
              <el-text>
                  准备好开启您的智能测试之旅了吗？
                  在这里，您可以轻松创建并管理您的AI测试任务项目。<br>
                  高效，从这里开始！
              </el-text>
          </el-main>
      </el-container>


      <!-- Dialog for i0 (InitialInput - Document Upload) -->
      <el-dialog
          v-model="ed.dialogVisible"
          title="新建项目 - InitialInput"
          width="600px"
          :before-close="U.f02_handleClose"
          class="minimalist-dialog"
      >
          <el-form
              ref="rf1"
              :rules="rules"
              :model="ed.i0" label-width="auto" label-position="left"
          >
              <el-form-item label="项目ID" prop="projectId">
                  <el-input v-model="ed.i0.projectId" placeholder="请输入项目ID" />
              </el-form-item>
              
              <el-form-item label="项目名称" prop="projectName">
                  <el-input v-model="ed.i0.projectName" placeholder="请输入项目名称" />
              </el-form-item>

              <el-form-item label="附加信息" prop="notes">
                  <el-input v-model="ed.i0.notes" placeholder="补充信息" :rows="3" type="textarea" />
              </el-form-item>

              <el-form-item label="SoW文档" class="file-upload-item">
                  <div class="file-upload-wrapper">
                      <el-button v-if="!ed.i0.sowDocx" :icon="Upload" @click="$refs.sowInput.click()">
                          选择文件
                      </el-button>
                      <input ref="sowInput" type="file" @change="U.i0_onSowChanged" style="display: none;" />
                      <div v-if="ed.i0.sowDocx" class="file-info">
                          <el-icon><Document /></el-icon>
                          <span>{{ ed.i0.sowDocx.name }} ({{humanizeBytes(ed.i0.sowDocx.size)}})</span>
                          <el-button @click="ed.i0.sowDocx = null" text :icon="Close" />
                      </div>
                  </div>
              </el-form-item>

              <el-form-item label="CLI文档" class="file-upload-item">
                  <div class="file-upload-wrapper">
                      <el-button v-if="!ed.i0.cliDocx" :icon="Upload" @click="$refs.cliInput.click()">
                          选择文件
                      </el-button>
                      <input ref="cliInput" type="file" @change="U.i0_onCliChanged" style="display: none;" />
                      <div v-if="ed.i0.cliDocx" class="file-info">
                          <el-icon><Document /></el-icon>
                          <span>{{ ed.i0.cliDocx.name }} ({{humanizeBytes(ed.i0.cliDocx.size)}})</span>
                          <el-button @click="ed.i0.cliDocx = null" text :icon="Close" />
                      </div>
                  </div>
              </el-form-item>

              <el-alert 
                  v-if="ed.err"
                  :title="ed.err"
                  type="error"
                  :closable="false"
                  show-icon
                  class="error-alert"
              />

              <div class="dialog-footer">
                  <el-button @click="ed.dialogVisible = false">取消</el-button>
                  <el-button @click="U.i0_reset">清空</el-button>
                  <el-button type="primary" @click="U.i0_submit(rf1)" :loading="ed.loading">
                      创建项目
                  </el-button>
              </div>

          </el-form>
      </el-dialog>

      <!-- Dialog for i1 (TestCase - Manual Configuration) -->
      <el-dialog
          v-model="ed.dialogVisible1"
          title="新建项目 - TestCase"
          width="700px"
          :before-close="U.f02_handleClose"
          class="minimalist-dialog"
      >
          <el-form
              ref="rf2"
              :rules="rules1"
              :model="ed.i1"
              label-width="auto"
              label-position="left"
          >
              <el-form-item label="项目ID" prop="projectId">
                  <el-input v-model="ed.i1.projectId" placeholder="请输入项目ID" />
              </el-form-item>
              
              <el-form-item label="项目名称" prop="projectName">
                  <el-input v-model="ed.i1.projectName" placeholder="请输入项目名称" />
              </el-form-item>

              <el-form-item label="附加信息" prop="notes">
                  <el-input v-model="ed.i1.notes" placeholder="补充信息" :rows="3" type="textarea" />
              </el-form-item>

              <el-form-item label="网络拓扑文件" prop="topox" class="file-upload-item">
                  <div class="file-upload-wrapper">
                      <el-button v-if="!ed.i1.topox" :icon="Upload" @click="$refs.topoxInput.click()">
                          选择文件
                      </el-button>
                      <input ref="topoxInput" type="file" accept=".txt,.yaml,.yml,.json" @change="U.i1_onTopoxChanged" style="display: none;" />
                      <div v-if="ed.i1.topox" class="file-info">
                          <el-icon><Document /></el-icon>
                          <span>{{ ed.i1.topox.name }} ({{humanizeBytes(ed.i1.topox.size)}})</span>
                          <el-button @click="ed.i1.topox = null" text :icon="Close" />
                      </div>
                  </div>
              </el-form-item>

              <el-form-item label="Pytest配置文件" prop="conftestPy" class="file-upload-item">
                  <div class="file-upload-wrapper">
                      <el-button v-if="!ed.i1.conftestPy" :icon="Upload" @click="$refs.conftestInput.click()">
                          选择文件
                      </el-button>
                      <input ref="conftestInput" type="file" accept=".py" @change="U.i1_onConftestChanged" style="display: none;" />
                      <div v-if="ed.i1.conftestPy" class="file-info">
                          <el-icon><Document /></el-icon>
                          <span>{{ ed.i1.conftestPy.name }} ({{humanizeBytes(ed.i1.conftestPy.size)}})</span>
                          <el-button @click="ed.i1.conftestPy = null" text :icon="Close" />
                      </div>
                  </div>
              </el-form-item>

              <el-form-item label="测试步骤">
                  <U08MagicEditor :kind="'test_steps'" :disabled="false"  v-model:text="ed.i1.test_steps" />
              </el-form-item>

              <el-alert v-if="ed.err1"
                  :title="ed.err1"
                  type="error"
                  :closable="false"
                  show-icon
                  class="error-alert"
              />

              <div class="dialog-footer">
                  <el-button @click="ed.dialogVisible1 = false">取消</el-button>
                  <el-button @click="U.i1_reset">清空</el-button>
                  <el-button type="primary" @click="U.i1_submit(rf2)" :loading="ed.loading">
                      创建项目
                  </el-button>
              </div>
          </el-form>
      </el-dialog>

      <U06TableC1
          :df="ed.D[1].df"
          v-model:q01_pageIdx="ed.D[1].pg.q01_pageIdx" :q02_totalCount="ed.D[1].pg.q02_totalCount"
          v-model:q03_pageSize="ed.D[1].pg.q03_pageSize"
          v-model:q04_projectName="ed.D[1].pg.q04_projectName"
          v-model:q05_sort="ed.D[1].pg.q05_sort"
          v-model:q06_ascending="ed.D[1].pg.q06_ascending"
          :loading="ed.loading" @f00_getChains="U.f00_getChains"
          @f01_handleFilter="U.f01_handleFilter" >
          <div class="ai-header" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;">
              <div>
                  <h4> <span style="color: var(--el-color-primary);"> 进行中 </span>任务链路列表</h4>
                  <el-text class="ai-sec-desc">
                      这里是所有正在运行的任务链路信息.
                  </el-text>
              </div>
              <div style="position:relative;">
                  <span style="position:absolute;bottom:0;right:0;">
                      <el-button type="primary" @click="ed.dialogVisible = true">
                          📄  从 InitialInput 新建项目
                      </el-button>
                      <el-button type="success" @click="ed.dialogVisible1 = true" style="margin-left: 10px;">
                          🧪 从 TestCase 新建项目
                      </el-button>
                  </span>
              </div>
          </div>
      </U06TableC1>

      <U06TableC1
          :df="ed.D[0].df" v-model:q01_pageIdx="ed.D[0].pg.q01_pageIdx" :q02_totalCount="ed.D[0].pg.q02_totalCount"
          v-model:q03_pageSize="ed.D[0].pg.q03_pageSize"
          v-model:q04_projectName="ed.D[0].pg.q04_projectName"
          v-model:q05_sort="ed.D[0].pg.q05_sort"
          v-model:q06_ascending="ed.D[0].pg.q06_ascending"
          :loading="ed.loading" @f00_getChains="U.f00_getChains"
          @f01_handleFilter="U.f01_handleFilter"
      >
          <div class="ai-header">
              <h4> <span style="color: var(--el-color-info);">
                      已结束 </span>任务链路列表</h4>
              <el-text class="ai-sec-desc">
                  这里是所有已经运行结束了的任务链路信息.
              </el-text>
          </div>
      </U06TableC1>

    </div>
</template>

<script setup lang="ts">
 import useUserStore from '@/store/modules/user'
 const U1 = useUserStore();

 import U08MagicEditor from '@/components/U08MagicEditor.vue';
 import { watch, ref, onMounted, reactive } from 'vue';
 import { Upload, Document, Close} from '@element-plus/icons-vue';
 import { ElMessage } from 'element-plus'
 import { humanizeBytes } from '@/utils/u';
 import U02Anim from '@/components/U02Anim.vue';
 import U06TableC1 from '@/components/U06TableC1.vue';
 import {S, TChain, ChainItem, TestChainInfo, r06postChain,pageIt,
         r02getChainInfos,sleep} from '@/api/hi_api';
 import type { FormInstance } from 'element-plus'

 import { useRouter } from 'vue-router';
 const router = useRouter();


 class UInput01 {
     // the input for the second part of the form
     projectId: string = "";
     projectName: string = "";
     notes: string = "";
     test_steps: string = "[]";
     topox: File | null = null;// text file
     conftestPy: File | null = null; // text file


     static rules(){
         return {
             projectId: [UInput.R_non_empty("项目ID")],
             projectName: [UInput.R_non_empty("项目名称")],
             notes: [],
         }
     }

     async giveInputChain(): Promise<TChain> {
         // 2.1 create a new chain
         let ch = new TChain("");// 🦜 : empty cid means new chain
         // 1. the dummy initial input
         let o = new ChainItem();
         o.klass = S.InitialInput;
         o.notes = this.notes;
         o.P.set("projectId", this.projectId);
         o.P.set("projectName", this.projectName);
         o.P.set("sowDocx64", "");
         o.P.set("cliDocx64", "");

         ch.L.push(o);// 🦜: start the one-item chain
         // 2. the NetworkSetup
         o = new ChainItem();
         o.klass = S.NetworkSetup;
         o.P.set("id", "");
         o.P.set("topox", this.topox ? await this.topox.text() : "");
         o.P.set("conftestPy", this.conftestPy ? await this.conftestPy.text() : "");
         o.notes = "<NetworkSetup as InitialInput>";
         ch.L.push(o);// 🦜: start the one-item chain
         // 3. the TestCase

         o = new ChainItem();
         o.klass = S.TestCase;
         o.P.set("name", "");
         o.P.set("test_steps", this.test_steps);
         o.notes = "<TestCase as InitialInput>";
         ch.L.push(o);// 🦜: start the one-item chain

         // 4. green them all before uploading them
         for (let x of ch.L){
             x.add_new0_F();
             x.add_greened_F();
         }
         return ch;
     }

    static check_textFile(f: File | null,
                          suffixes: string[],
                          m: string): string {
        // return error message, "" on success
        if (f === null || f === undefined) {
            return `请上传一个有效的${m}文档. `;
        }
        const fileName = f.name.toLowerCase();
        const hasValidSuffix = suffixes.some(suffix => fileName.endsWith(suffix.toLowerCase()));
        if (!hasValidSuffix) {
            return `上传的${m}文档格式不正确, name = ${f.name}，请上传以下格式之一: ${suffixes.join(', ')}. `;
        }else if (f.size > 10 * 1024 * 1024) { // 10 MB limit
            return `上传的${m}文档过大，请上传一个小于10MB的文件.  `;
        }else {
            return ""; // no error
        }
    }
 }

 class UInput {
     sowDocx: File | null = null;
     cliDocx: File | null = null;
     projectId: string = "";
     projectName: string = "";
    notes: string = "";

    async giveInitialInput(): Promise<ChainItem> {
        // split the ChainItem according to the input
        let o = new ChainItem();
        o.klass = S.InitialInput;
        o.notes = this.notes;
        o.P.set("projectId", this.projectId);
        o.P.set("projectName", this.projectName);
        if (!this.sowDocx || !this.cliDocx) {
            throw new Error("SOW and CLI documents must be provided. before calling toJson.");
        }
        o.P.set("sowDocx64", await UInput.toBase64(this.sowDocx) as string);
        o.P.set("cliDocx64", await UInput.toBase64(this.cliDocx) as string);
        return o;
    }

    static toBase64 = (f: File) => new Promise((resolve, reject) => {
        const r = new FileReader();
        r.readAsDataURL(f);
        r.onload = () => resolve(r.result ? (r.result as string).replace(/^.*,/, '') : '');
        // 🦜 : the real b64 content is after the , char, so ^ here we zap to the , char
        r.onerror = reject;
    });


    static R_non_empty(m: string){
        return { required: true, message: `${m}不能为空`, trigger: 'blur' };
    }
    check_sow(): string{
        return UInput.check_docx(this.sowDocx, "SOW文档");
    }
    check_cli(): string{
        return UInput.check_docx(this.cliDocx, "CLI文档");
    }
    static check_docx(f: File | null, m: string): string {
        // return error message, "" on success
        if (f === null || f === undefined) {
            return `请上传一个有效的${m}文档. `;
        }else if (
            !f.name.toLowerCase().endsWith(".docx") &&
            !f.name.toLowerCase().endsWith(".doc") &&
            !f.name.toLowerCase().endsWith(".docm")
        )
            {
            return `上传的${m}文档格式不正确, name = ${f.name}，请上传一个.docx文件, 且文件名以.docx或.doc结尾. `;
        }else if (f.size > 10 * 1024 * 1024) { // 10 MB limit
            return `上传的${m}文档过大，请上传一个小于10MB的文件.  `;
        }else {
            return ""; // no error
        }
    }

     static rules(){
         return {
             projectId: [UInput.R_non_empty("项目ID")],
             projectName: [UInput.R_non_empty("项目名称")],
             notes: [],
         }
     }
 }



 class PG {
     constructor(
         public q01_pageIdx: number, // 🦜 : page index starts from 1
         public q02_totalCount: number,
         public q03_pageSize: number,
         public q04_projectName: string,
         public q05_sort: "cid" | "projectName" = "cid",
         public q06_ascending: boolean = true // 🦜 : ascending order
    ) {}
 }// 🦜 : same as the one in hi_api.ts, but let's just copy it for display..
interface D0{pg: PG; df: TestChainInfo[];}
 // Form data
 const ed = reactive({
     D : [
         {pg : new PG(1, 0, 5, ""), df : [] as TestChainInfo[] },
         {pg : new PG(1, 0, 5, ""), df : [] as TestChainInfo[] },
         ] as D0[],

     i0: new UInput(),
     i1: new UInput01(),

     loading: false,
     now: new Date(),
     df: [] as TestChainInfo[], //  the table data
     dialogVisible: false, // 🦜 : for the i0 dialog (InitialInput)
     dialogVisible1: false, // 🦜 : for the i1 dialog (TestCase)
     err: "", // validation error for i0
     err1: "" // validation error for i1
 });

 const rules = UInput.rules();
 const rules1 = UInput01.rules();
 const rf1 = ref<FormInstance>()
 const rf2 = ref<FormInstance>()// 🦜 : this is a special case where we can't put this inside 
 
 import { U2 } from '@/utils/u';

 // wathers: " 🦜 : 
 watch(() => ed.D[0].pg.q04_projectName, async (xnew,x) => {
     console.log('🦜: q04_projectName changed to:', xnew);
     await U.f01_handleFilter();
 });

 class U{
     static view = (row: TestChainInfo) => {
         console.log("viewing row: ", row);
         // Navigate to the edit page with the cid
         if (row && row.cid) {
             router.push({ name: 'chain-view', params: { cid: row.cid } });
         } else {
             console.error('Invalid row data for editing', row);
         }
     };
     static start_loading(s: string = "Loading") {ed.loading = U2.start_loading(s);}
     static stop_loading() {ed.loading = U2.stop_loading();}
     static resetForm = async (formEl: FormInstance | undefined) => {
         if (!formEl) return
         formEl.resetFields()
     }

     static f01_handleFilter = () => {
         let S = [ed.D[0].pg.q04_projectName, ed.D[1].pg.q04_projectName];
         let Done = [true, false];

         console.log("Filtering with query: q0 = ", S[0],
                     "q01_pageIdx", ed.D[0].pg.q01_pageIdx,
                     "q03_pageSize", ed.D[0].pg.q03_pageSize
         );
         console.log("Filtering with query: q1 = ", S[1],
                     "q01_pageIdx", ed.D[1].pg.q01_pageIdx,
                     "q03_pageSize", ed.D[1].pg.q03_pageSize
         );

         function f02_sortIt(o: TestChainInfo[], q05_sort: string, q06_ascending: boolean): TestChainInfo[]{
             let n = q06_ascending ? 1 : -1;
             if (q05_sort ===  "projectName"){
                 o.sort((a, b) => {
                     return a.projectName.localeCompare(b.projectName) * n;
                 });
             }else { // cid
                 o.sort((a, b) => {
                     let na = parseInt(a.cid.replace('cid-', ''), 10);
                     let nb = parseInt(b.cid.replace('cid-', ''), 10);
                     return (na - nb)* n;
                 });
             }
             return o;
         }

         for (let i = 0; i < 2; i++) {
             let o = ed.df.filter((x: TestChainInfo) => {
                 return (x.done === Done[i]) && x.projectName.includes(S[i]);
             });
             // 2. sort it
             o = f02_sortIt(o, ed.D[i].pg.q05_sort, ed.D[i].pg.q06_ascending);
             // 3. page it
             o = pageIt<TestChainInfo>(o , ed.D[i].pg.q03_pageSize, ed.D[i].pg.q01_pageIdx);
             ed.D[i].df = o.l;
             ed.D[i].pg.q02_totalCount = o.q02_totalCount;
         }
     }
     static f02_handleClose = (done: () => void) => {
         done();
     };


     static i0_reset = () => {
         console.log("resetting UInput: ", ed.i0);
         // i0.sowDocx = i0.cliDocx = null;
         // i0.notes = i0.projectId = i0.projectName = "";
         ed.err = "";
         ed.i0 = new UInput();// 🦜 : we can do it only because it's a field noe
     };
     static i0_onCliChanged = (e: Event) => {
         const i = e.target as HTMLInputElement;
         if (i.files && i.files.length > 0) {
             ed.i0.cliDocx = i.files[0];
             console.log(`docx uploaded for ${ed.i0.cliDocx.name}`, ed.i0.cliDocx);
         }
     };
     static i0_onSowChanged = (e: Event) => {
         const i = e.target as HTMLInputElement;
         if (i.files && i.files.length > 0) {
             ed.i0.sowDocx = i.files[0];
             console.log(`docx uploaded for ${ed.i0.sowDocx.name}`, ed.i0.sowDocx);
         }
     };

     static i1_reset = () => {
         console.log("resetting UInput01: ", ed.i1);
         ed.err1 = "";
         ed.i1 = new UInput01();
     };

     static i1_onTopoxChanged = (e: Event) => {
         const i = e.target as HTMLInputElement;
         if (i.files && i.files.length > 0) {
             ed.i1.topox = i.files[0];
             console.log(`topox file uploaded: ${ed.i1.topox.name}`, ed.i1.topox);
         }
     };

     static i1_onConftestChanged = (e: Event) => {
         const i = e.target as HTMLInputElement;
         if (i.files && i.files.length > 0) {
             ed.i1.conftestPy = i.files[0];
             console.log(`conftest.py uploaded: ${ed.i1.conftestPy.name}`, ed.i1.conftestPy);
         }
     };

     static i0_validate0 = async (formEl: FormInstance | undefined) => {
         if (!formEl) return false;
         let ok = false;
         await formEl.validate((valid, fields) => {
             if (valid) {
                 console.log('✅️ El validate passed!')
                 ok = true;
             } else {
                  console.log('❌️ El validate failed!', fields);
             }
         })
         return ok;
     };

     static i0_validate(): boolean {
         let err1 = ed.i0.check_sow();
         let err2 = ed.i0.check_cli();
         // ok if both are ""
         ed.err = err1 + err2;
         return (err1 === "" && err2 === "")
     }

     static i1_validate0 = async (formEl: FormInstance | undefined) => {
        if (!formEl) return false;
        let ok = false;
        await formEl.validate((valid, fields) => {
            if (valid) {
                console.log('✅️ El validate passed for i1!')
                ok = true;
            } else {
                 console.log('❌️ El validate failed for i1!', fields);
            }
        })
        return ok;
    };

    static i1_validate(): boolean {
        let err1 = UInput01.check_textFile(ed.i1.topox, ['.topox'], "网络拓扑");
        let err2 = UInput01.check_textFile(ed.i1.conftestPy, ['.py'], "Pytest配置");
        ed.err1 = err1 + err2;
        return (err1 === "" && err2 === "")
    }

    static async i1_submit(formEl: FormInstance | undefined) {
        ed.err1 = "";
        console.log("Submitting UInput01: ", ed.i1);
        console.log("Form instance: ", formEl);
        U.start_loading("Trying to create a new test project with manual configuration...");
        let ok = await U.i1_validate0(formEl);
        if (!ok){
            U.stop_loading(); return;
        }

        // 0. check input
        if (!U.i1_validate()) {
            U.stop_loading(); return;
        }
        // 1. create the chain with all items
        try{
            let ch = await ed.i1.giveInputChain();
            let o = await r06postChain(ch);
            if (o.code != 0){
                console.error("Failed to create new test project", o);
            }else{
                U.showSuccess("新的测试项目创建成功");
                U.i1_reset();
                ed.dialogVisible1 = false;
                console.log("✅️ New test project created successfully with manual config", o);
                await sleep(1);
                await U.f00_getChains(); // 🦜 : refresh the list
            }
        } finally {
            U.stop_loading();
        }
    }

    static async i0_submit(formEl: FormInstance | undefined) {
         ed.err = "";
         console.log("Submitting UInput: ", ed.i0);
         console.log("Form instance: ", formEl);
         U.start_loading("Trying to create a new test project...");
         let ok = await U.i0_validate0(formEl);
         if (!ok){
             U.stop_loading(); return;
         }

         // 0. check input
         if (!U.i0_validate()) {
             U.stop_loading(); return;
         }
         // 1. set the create flag with User-token before sending to front end
         let i0 = await ed.i0.giveInitialInput();
         i0.add_new0_F();
         i0.add_greened_F();
         // 2. post
         try{
             // 2.1 create a new chain
             let ch = new TChain("");// 🦜 : empty cid means new chain
             ch.L.push(i0);// 🦜: start the one-item chain
             let o = await r06postChain(ch);
             if (o.code != 0){
                 // U.showError(`创建失败: ${o.msg}`); // 🦜 : request.js will warn us
                 console.error("Failed to create new test project", o);
             }else{
                 U.showSuccess("新的测试项目创建成功");
                 U.i0_reset();
                ed.dialogVisible = false;
                 console.log("✅️ New test project created successfully", o);
                 await sleep(1);
                 await U.f00_getChains(); // 🦜 : refresh the list
                 // 3. reset the form
             }
         } finally {
             U.stop_loading();
         }
     }

     static showError(o: string){
         console.log(`❌️ ${o}`);
         ElMessage({message: o, type: 'error',});
     }

     static showSuccess(o: string){
         // ElNotification({title: 'Success', message: o, type: 'error',});
         ElMessage({message: o, type: 'success',});
     }

     static f00_getChains = async () => {
         // Fetch TestChainInfo list
         try {
             ed.loading = true;
             const res = await r02getChainInfos(false, {
                 q01_pageIdx: 1,
                 q03_pageSize: 0xffff
                 }
             );
             // type ED2<T> = [T[], number, number]; // (current page items, total items, total pages)
             if (res && Array.isArray(res.data.l)) {
                 ed.df = res.data.l;
                 U.f01_handleFilter();
             } else {
                  console.error('Unexpected response format', res);
              }
             ed.loading = false;
         } catch (e) {
             console.error('Failed to fetch chains', e);
         }
     };
 };


 onMounted(async () => {
     // 🦜 : try send a mocked ii
     // let i0 = ed.i0;
     // i0.notes = "Initial input for the test chain";
     // i0.projectId = "test-project-123";
     // i0.projectName = "Test Project";
     // const blob = new Blob(['hi']); // the blob
     // i0.sowDocx = new File([blob], "hi.docx",{ type: "image/png" })
     // i0.cliDocx = new File([blob], "hi.doc",{ type: "image/png" })
     // let o = await r01newTestProject(i0);

     await U.f00_getChains()
 });
</script>

<style lang="scss">
@use 'base';

// Minimalist Dialog Styling
.minimalist-dialog {
  :deep(.el-dialog__header) {
    padding: 24px 24px 16px;
    border-bottom: 1px solid #f0f0f0;
    
    .el-dialog__title {
      font-size: 18px;
      font-weight: 500;
      color: #303133;
    }
  }
  
  :deep(.el-dialog__body) {
    padding: 24px;
  }
  
  :deep(.el-dialog__footer) {
    padding: 0;
  }
  
  .el-form {
    .el-form-item {
      margin-bottom: 20px;
      
      :deep(.el-form-item__label) {
        font-weight: 400;
        color: #606266;
        margin-bottom: 8px;
      }
    }
    
    .file-upload-item {
      .file-upload-wrapper {
        .file-info {
          display: flex;
          align-items: center;
          gap: 8px;
          padding: 8px 12px;
          background-color: #f5f7fa;
          border-radius: 4px;
          
          .el-icon {
            color: #909399;
          }
          
          span {
            flex: 1;
            color: #606266;
            font-size: 14px;
          }
        }
      }
    }
    
    .error-alert {
      margin-top: 16px;
      margin-bottom: 0;
    }
    
    .dialog-footer {
      display: flex;
      justify-content: flex-end;
      gap: 12px;
      margin-top: 24px;
      padding-top: 20px;
      border-top: 1px solid #f0f0f0;
    }
  }
}

// Keep only essential table styles
.el-table {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
  min-height: 300px;
}

.el-card {
  background-color: rgba(255, 255, 255, 0.5);
  border-radius: 10px;
}

.ai-header {
  margin-bottom: 1rem;
  
  h4 {
    margin: 0 0 0.5rem 0;
    color: #303133;
    font-weight: 600;
  }
  
  .ai-sec-desc {
    color: #606266;
    font-size: 14px;
  }
}
</style>
